package com.myk.game.gobangchess.rooms.oldrooms;

import com.myk.game.gobangchess.DataManager;
import com.myk.game.gobangchess.Room;
import com.myk.game.gobangchess.Sign;
import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.AroundSign;
import com.myk.game.gobangchess.signs.GroundSign;
import com.myk.game.gobangchess.signs.LineSign;
import com.myk.game.gobangchess.utils.GridsUtils;
import sun.invoke.empty.Empty;

import java.util.ArrayList;
import java.util.List;

/**
 * 阴阳五子棋房间
 */
public class YinYangGoBangRoom extends Room {

    private static final int[][] directions = {{1, 0}, {0, 1}, {1, 1}, {1, -1}};

    private static final int[][] kingMoves = {{-1, 1}, {-1, 0}, {-1, -1}, {0, 1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}};

    private static final int EMPYTY_PIECE = 0;
    private static final int BLACK_PIECE = 1;
    private static final int WHITE_PIECE = 2;
    private static final int HALF_PIECCE = 8;

    protected List<Sign> tempPointSigns = new ArrayList<>(); //记录最新落点的标记
    protected List<Sign> permanentPointSigns = new ArrayList<>(); //记录五连的标记
    private Point[][] points;


    public YinYangGoBangRoom(String roomName) {
        super(roomName, "\t\t阴阳五子棋", "阴阳五子棋", BoardStyleData.getGoBangStyle(15, 15), true, true);
    }

    @Override
    public String getRuleText() {
        return "黑白双方，轮流落1子\n" +
                "\n" +
                "如果一个对方棋子周围的己方棋子少于对方棋子，则可以放弃落子，点一下该棋子将其变为“阴阳子”\n" +
                "\n" +
                "己方棋子连五时获得1分（长连也能得分，但同一个连五不能重复得分），阴阳子被视为双方棋子，可以参与连五并得分\n" +
                "\n" +
                "5分为胜";
    }

    @Override
    protected void doStart() {
        blackScore = 0;
        whiteScore = 0;
//        super.doStart();
        DataManager.noticeAllGameStart(player_black, player_white, roomName);
        overFlag = 1;//重置结束状态：对弈进行中未结束
        playingStartTime = System.currentTimeMillis(); //重置对弈开始时间
        resetGrids();
        noticeBlackMove();
        preHistory();
//        super.doStart();
        points = new Point[curGrids.length][curGrids[0].length];
        for (int i = 0; i < curGrids.length; i++) {
            for (int j = 0; j < curGrids[0].length; j++) {
                points[i][j] = new Point();
            }
        }
    }

    @Override
    public void doRule(int row, int col, int value) {
        int thisPiece = curGrids[row][col];
        if (thisPiece == EMPYTY_PIECE) {
            curGrids[row][col] = cur;
        } else if (thisPiece == BLACK_PIECE) {
            int blackNum = 0;
            int whiteNum = 0;

            if (cur == 2) {
                boolean isExisted = true;
                for (int[] move : kingMoves) {
                    int nextRow = row + move[0];
                    int nextCol = col + move[1];
                    if (nextCol >= curGrids[0].length || nextRow >= curGrids.length ||nextCol <0 || nextRow <0) {
                        isExisted = false;
                        break;
                    }
                    int thisP = curGrids[nextRow][nextCol];
                    if (thisP == 1) {
                        blackNum++;
                    } else if (thisP == 2) {
                        whiteNum++;
                    }
                }
                if (!isExisted)
                    return;
                if (whiteNum < blackNum) {
                    curGrids[row][col] = HALF_PIECCE;
                } else
                    return;
            } else
                return;
        } else if (thisPiece == WHITE_PIECE) {
            int blackNum = 0;
            int whiteNum = 0;
            boolean isExisted = true;
            if (cur == 1) {
                for (int[] move : kingMoves) {
                    int nextRow = row + move[0];
                    int nextCol = col + move[1];
                    if (nextCol >= curGrids[0].length || nextRow >= curGrids.length ||nextCol <0 || nextRow <0) {
                        isExisted = false;
                        break;
                    }
                    int thisP = curGrids[nextRow][nextCol];
                    if (thisP == 1) {
                        blackNum++;
                    } else if (thisP == 2) {
                        whiteNum++;
                    }
                }
                if (!isExisted)
                    return;
                if (whiteNum > blackNum) {
                    curGrids[row][col] = HALF_PIECCE;
                } else
                    return;
            } else
                return;
        } else
            return;

        tempPointSigns.add(new GroundSign(getIndex(row, col), "#00000000", ColorCost.NEW_PUT_POINT, 1.0f, 0, 0));
        stepAdd();
        int addScore = checkLine();
        if (addScore != 0) {
            String text = cur == 1 ? "黑方" : "白方";
            gameTip = text + "获得" + addScore + "分";
        }
        changeMove();
    }

    @Override
    public String getGameInfo() {
        signList.clear();
        signList.addAll(tempPointSigns);
        signList.addAll(permanentPointSigns);
        List<Integer> canHalfPoints = new ArrayList<Integer>();
        List<Integer> canHalfPoints1 = new ArrayList<Integer>();
        //提示是否可以替换阴阳子
        if (step > 1) {
            for (int i = 0; i < curGrids.length; i++) {
                for (int j = 0; j < curGrids[0].length; j++) {
                    int blackNum = 0;
                    int whiteNum = 0;
                    boolean isExisted = true;
                    if (curGrids[i][j] == (cur == 1 ? WHITE_PIECE : BLACK_PIECE)) {
                        for (int[] move : kingMoves) {
                            int nextRow = i + move[0];
                            int nextCol = j + move[1];
                            if (nextCol >= curGrids[0].length || nextRow >= curGrids.length||nextCol <0 || nextRow <0) {
                                isExisted = false;
                                break;
                            }
                            int thisP = curGrids[nextRow][nextCol];
                            if (thisP == 1) {
                                blackNum++;
                            } else if (thisP == 2) {
                                whiteNum++;
                            }
                        }
                        if (isExisted)
                            if (cur == 1 ? (blackNum < whiteNum) : (blackNum > whiteNum)) {
                                canHalfPoints.add(getIndex(i, j));
                            }
                    }
                }
            }
            for (int i = 0; i < curGrids.length; i++) {
                for (int j = 0; j < curGrids[0].length; j++) {
                    int blackNum = 0;
                    int whiteNum = 0;
                    boolean isExisted = true;
                    if (curGrids[i][j] == (cur == 1 ?BLACK_PIECE: WHITE_PIECE )) {
                        for (int[] move : kingMoves) {
                            int nextRow = i + move[0];
                            int nextCol = j + move[1];
                            if (nextCol >= curGrids[0].length || nextRow >= curGrids.length||nextCol <0 || nextRow <0) {
                                isExisted = false;
                                break;
                            }
                            int thisP = curGrids[nextRow][nextCol];
                            if (thisP == 1) {
                                blackNum++;
                            } else if (thisP == 2) {
                                whiteNum++;
                            }
                        }
                        if (isExisted)
                            if (cur == 1 ?  (blackNum > whiteNum):(blackNum < whiteNum) ) {
                                canHalfPoints1.add(getIndex(i, j));
                            }
                    }
                }
            }
        }
        if (!canHalfPoints.isEmpty())
            if (cur == 1)
                signList.add(new AroundSign(canHalfPoints, "#BB444444", "#00000000", 1.0f));
            else if (cur == 2)
                signList.add(new AroundSign(canHalfPoints, "#CCEEEEEE", "#00000000", 1.0f));
        if (!canHalfPoints1.isEmpty())
            if (cur == 2)
                signList.add(new AroundSign(canHalfPoints1, "#BB444444", "#00000000", 1.0f));
            else if (cur == 1)
                signList.add(new AroundSign(canHalfPoints1, "#CCEEEEEE", "#00000000", 1.0f));
        return super.getGameInfo();

    }

    private void changeMove() {
        if (!checkWin()) {
            if (cur == 2) {
                noticeBlackMove();
            } else if (cur == 1) {
                noticeWhiteMove();
            }
        }
        gameTip = "";
        tempPointSigns = new ArrayList<>();
    }

    private boolean checkWin() {
        int blankNum = GridsUtils.getDataCount(curGrids, 0);  //没有胜负也没有空子了算战平
        if (blankNum == 0) {
            if (blackScore == whiteScore){
                doOver(WinMode.BOTH_DRAW, player_black.getNickNameOrTemp() + "-黑棋战平" + player_white.getNickNameOrTemp() + "-白棋");
                return true;
            } else if (blackScore>whiteScore) {
                doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp());
                return true;
            } else {
                doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp());
                return true;
            }
        } else if (blackScore >= 5) {
            doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp());
            return true;
        } else if (whiteScore >= 5) {
            doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp());
            return true;
        }
        return false;
    }

    public int checkLine() {
        int addScore = 0;
        List<int[]> winningPoints = new ArrayList<>();
        for (int i = 0; i < curGrids.length; i++) {
            for (int j = 0; j < curGrids[0].length; j++) {
                if (cur == 1) {
                    if (curGrids[i][j] == BLACK_PIECE || curGrids[i][j] == HALF_PIECCE) {
                        for (int k = 0; k < directions.length; k++) {
                            if ((points[i][j]).blackIsLine[k])
                                continue;
                            int[] direction = directions[k];
                            winningPoints = findWinningLine(curGrids, i, j, cur, k);
                            if (!winningPoints.isEmpty()) {
                                if (cur == 1) {
                                    for (int[] p : winningPoints) {
                                        Point pp = points[p[0]][p[1]];
                                        pp.blackIsLine[k] = true;
                                    }
                                }
                                blackScore++;
                                addScore++;
                            }
                        }
                    }
                } else if (cur == 2) {
                    if (curGrids[i][j] == WHITE_PIECE || curGrids[i][j] == HALF_PIECCE) {
                        for (int k = 0; k < directions.length; k++) {
                            if ((points[i][j]).whiteIsLine[k])
                                continue;
                            int[] direction = directions[k];
                            winningPoints = findWinningLine(curGrids, i, j, cur, k);
                            if (!winningPoints.isEmpty()) {
                                if (cur == 2) {
                                    for (int[] p : winningPoints) {
                                        Point pp = points[p[0]][p[1]];
                                        pp.whiteIsLine[k] = true;
                                    }
                                }
                                whiteScore++;
                                addScore++;
                            }
                        }
                    }
                }
            }
        }
        return addScore;
    }

    private List<int[]> findWinningLine(int[][] board, int x, int y, int player, int k) {
        int[] direction = directions[k];
        List<int[]> pointss = new ArrayList<>();
        int count = 0;
        int i = x;
        int j = y;

        while (i >= 0 && i < board.length && j >= 0 && j < board[0].length && (board[i][j] == player || board[i][j] == HALF_PIECCE)) {
            if (((points[i][j]).whiteIsLine[k] && cur == WHITE_PIECE) || ((points[i][j]).blackIsLine[k] && cur == BLACK_PIECE))
                return new ArrayList<>();
            pointss.add(new int[]{i, j});
            count++;
            i += direction[0];
            j += direction[1];
        }

        if (count >= 5) {
            permanentPointSigns.add(new LineSign(getIndex(pointss.get(0)[0],pointss.get(0)[1]),getIndex(pointss.get(count-1)[0],pointss.get(count-1)[1]),cur == 1?"#B2B2B2B2":"#B24C4C4C",0));
            return pointss;
        }

        return new ArrayList<>();
    }

    static class Point {
        boolean[] blackIsLine;//该位置黑子是否已经形成五连及以上,0为上下,1为左右,2为左上,3为右上
        boolean[] whiteIsLine;//该位置白子是否已经形成五连及以上,0为上下,1为左右,2为左上,3为右上

        public Point() {
            blackIsLine = new boolean[4];
            whiteIsLine = new boolean[4];
        }
    }

    @Override
    public void resetGrids() {
        tempPointSigns = new ArrayList<Sign>();
        permanentPointSigns = new ArrayList<Sign>();
        super.resetGrids();
    }
}
